<template>
  <div class="property-form">
    <a-form
      :form="form"
      :label-col="{ span: labelCol }"
      :wrapper-col="{ span: wrapperCol }"
    >
      <div
        v-if="panelList.length > 0"
        class="panel-title"
        @click="showFlag = !showFlag"
      >
        <div class="panel-title-hr"></div>
        样式
        <a-icon :type="showFlag ? 'down' : 'right'" />
      </div>
      <div v-show="showFlag">
        <div v-for="(panel, index) in panelList" :key="index" class="panel">
          {{ panel.label }}

          <template v-for="(item, i) in panel.children">
            <a-form-item
              v-if="item.type !== 'group' && item.type !== 'switch-group'"
              :key="`form-item-${i}`"
              :layout="item.layout"
              :class="item.layout"
            >
              <span slot="label">
                {{ item.label }}
                <a-tooltip
                  v-if="item.tooltip"
                  placement="top"
                  :mouse-leave-delay="0.5"
                >
                  <template slot="title">
                    {{ item.tooltip }}
                  </template>
                  <span
                    style="cursor: pointer;"
                    @mouseover="isAnnotationHover = true"
                    @mouseout="isAnnotationHover = false"
                  >
                    <a-icon-font
                      v-show="isAnnotationHover"
                      type="iconinfo-cirlce-obeifen"
                    />
                    <a-icon-font
                      v-show="!isAnnotationHover"
                      type="iconinfo-cirlce-o"
                    />
                  </span>
                </a-tooltip>
              </span>
              <component
                :is="getCompType(item)"
                v-decorator="getDecorator(item)"
                v-bind="{ ...item.props, ...commonFormProps }"
                :props="item.props"
              >
              </component>
            </a-form-item>
            <div v-else :key="`form-item-${i}`" class="group-form-item">
              <!-- 有分组，如：X轴组内包括标题、刻度、网格线 -->
              <div v-if="item.type === 'group'">{{ item.label }}</div>
              <a-form-item
                v-else
                :label="item.label"
                :layout="item.layout"
                :class="item.layout"
              >
                <a-switch
                  v-decorator="getDecorator(item)"
                  v-bind="{ ...item.props, ...commonFormProps }"
                  :props="item.props"
                >
                </a-switch>
              </a-form-item>
              <div
                v-show="item.type === 'group' || form.getFieldValue(item.name)"
                class="group-form-item-content"
              >
                <a-form-item
                  v-for="(child, cindex) in item.children"
                  :key="`form-subitem-${cindex}`"
                  :label="child.label"
                  :layout="child.layout"
                  :class="item.layout"
                  class="sub-form-item"
                >
                  <component
                    :is="getCompType(child)"
                    v-decorator="getDecorator(child)"
                    v-bind="{ ...child.props, ...commonFormProps }"
                    :props="child.props"
                  >
                  </component>
                </a-form-item>
              </div>
            </div>
          </template>
          <!-- <a-form-item
          v-for="(item, i) in panel.children"
          :key="`form-item-${i}`"
          :label="item.label"
          :layout="item.layout"
          :class="item.layout"
        >
          <component
            :is="getCompType(item)"
            v-decorator="getDecorator(item)"
            v-bind="{ ...item.props, ...commonFormProps }"
            :props="item.props"
          >
          </component>
        </a-form-item> -->
        </div>
      </div>
    </a-form>
  </div>
</template>

<script lang="ts">
/* eslint-disable unicorn/prevent-abbreviations */
import { Vue, Prop, Component, Watch } from 'vue-property-decorator'
import {
  dynamicCompMaps,
  dynamicComponent,
} from '@/components/common/VisualizationDashboard/util'
import { isEqual } from 'lodash'

export interface KeyValue {
  [key: string]: any
}

@Component({
  components: {
    ...dynamicComponent,
  },
})
export default class PropertyForm extends Vue {
  // 包含两种类型的panel，用type区分：fetch(和数据获取相关)、property(和图表属性配置相关)
  @Prop({ default: () => [] }) panelList!: KeyValue[]
  @Prop({
    type: Number,
    required: false,
    default() {
      return 8
    },
  })
  labelCol!: number

  @Prop({
    type: Number,
    required: false,
    default() {
      return 16
    },
  })
  wrapperCol!: number

  @Prop({
    type: Object,
    required: true,
    default(): KeyValue {
      return {}
    },
  })
  formData!: KeyValue

  private form: any
  private commonFormProps = {
    size: 'small',
  }

  private showFlag: boolean = true // 是否展开面板
  private isAnnotationHover = false //  icon tooltip hover status

  beforeCreate() {
    this.form = this.$form.createForm(this, {
      name: 'propertyForm',
      // onFieldsChange: () => {
      //   this.onFormFieldChange()
      // },
      // @ts-ignore
      onValuesChange: (formEle, changedValues, allValues) => {
        // eslint-disable-next-line prefer-rest-params
        if (!isEqual(changedValues, allValues)) {
          // 因为formData变化后会setFieldsValue一次，也会触发 valuesChange，所以对比是否一致
          this.onFormValueChange(allValues)
        }
      },
    })
    // @ts-ignore
    window._form = this.form
  }

  @Watch('formData', { immediate: true, deep: true })
  private onFormDataChange(newValue: KeyValue, oldValue: KeyValue) {
    if (isEqual(newValue, oldValue)) {
      return
    }
    this.setFormData()
  }

  /**
   * 设置表单 form 的值
   */
  private setFormData() {
    const {
      form: { getFieldsValue, setFieldsValue },
      formData,
    } = this
    this.$nextTick(() => {
      const values = getFieldsValue()
      const formDataKeysSet = new Set(Object.keys(formData))
      // 设置值时只能设定表单中有的字段
      Object.keys(values).forEach((k) => {
        if (formDataKeysSet.has(k)) {
          // formData 中有对应的key才进行赋值
          values[k] = formData[k]
        }
      })
      // resetFields()
      setFieldsValue(values)
    })
  }

  /**
   * 根据配置获取渲染的组件类型
   */
  private getCompType(item: KeyValue): string {
    const result = 'a-input'
    if (dynamicCompMaps[item.type]) {
      return dynamicCompMaps[item.type].component
    }
    return result
  }

  /**
   * 获取组件formItem 的 decorator
   * 必须，否则无法注册到form上
   */
  private getDecorator(field: KeyValue) {
    const that = this
    const options: KeyValue = { initialValue: field.defaultValue }
    if (field.type === 'switch' || field.type === 'switch-group') {
      options.valuePropName = 'checked'
    }
    if (field.name === 'yAxisMax' || field.name === 'yAxisMin') {
      const flag = field.name === 'yAxisMin'
      options.trigger = 'blur'
      options.rules = [
        {
          validator: (rule: any, value: any, callback: Function) => {
            if (value === '' || value === undefined || value === null) {
              // 过滤掉未配置最大最小值的项
              // console.log(flag,value,'value undefine')
              callback()
              return
            }
            if (Number.isNaN(Number(value))) {
              // console.log(flag,value,'value inlegal')
              callback('不合法的输入')
              return
            }
            const otherValue = that.form.getFieldValue(
              flag ? 'yAxisMax' : 'yAxisMin'
            )
            if (
              otherValue === '' ||
              otherValue === undefined ||
              otherValue === null ||
              Number.isNaN(Number(otherValue))
            ) {
              // console.log(flag,value,otherValue,'other value inlegal')
              callback()
              return
            }

            if (
              flag
                ? Number(value) > Number(otherValue)
                : Number(value) < Number(otherValue)
            ) {
              // console.log(flag,value,otherValue,'compare inlegal')
              callback(
                flag ? '最小边界应小于最大边界' : '最大边界应大于最小边界'
              )
            } else {
              // console.log(flag,value,otherValue,'ok')
              callback()
            }
            // that.form.validateFields([flag?'yAxisMax':'yAxisMin'], { force: false})
          },
        },
      ]
    }
    return [field.name, options]
  }

  /**
   * formItem 数值变化
   */
  private onFormValueChange(allValues: any) {
    const f = this.form
    this.$nextTick(() => {
      f.validateFields((error: any) => {
        if (!error) {
          this.$emit('change', allValues) // onValuesChange 方法回调时只能用回调的参数，getFieldsValue等方法会有延迟，未生效
        }
      })
    })
  }
}
</script>

<style lang="less" scoped>
.panel-title {
  font-weight: bolder;
  height: 40px;
  line-height: 40px;
  margin-top: 4px;
  position: relative;
  width: 100%;

  .anticon {
    font-size: 8px;
    font-weight: normal;
    height: 40px;
    line-height: 40px;
    position: absolute;
    right: 10px;
  }

  .panel-title-hr {
    background-color: #e9e9e9;
    height: 1px;
    left: -16px;
    position: absolute;
    right: -20px;
  }
}

.group-form-item .group-form-item-content {
  padding-bottom: 12px;
}

.property-form {
  /deep/ .ant-slider {
    margin: 8px 6px;
  }
}

/deep/ .ant-form-item-label {
  text-align: left;
}

/deep/ .ant-form-item.vertical {
  .ant-col {
    width: 100%;
  }
}

/deep/ .ant-form-item {
  margin-bottom: 0;
}

/deep/ .ant-form-item-label > label::after {
  content: '';
}
</style>
